/*******************************************************************************
 * Copyright (c) 2005, 2007 Bastian Bergerhoff and others
 * All rights reserved. This program and the accompanying materials 
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution.
 * 
 * Contributors:
 *     Bastian Bergerhoff - initial API and implementation, all but:
 *     Andreas Studer - Contributions to handling global flags
 *     Georg Sendt - Contributions to threaded evaluation, implementation of
 *                   JRegex-Flavour
 *******************************************************************************/
package org.outlook.eclipse.plugins.regexp4eclipse.views;

import java.lang.reflect.InvocationTargetException;
import java.util.Collection;
import java.util.Iterator;
import java.util.Vector;
import java.util.regex.PatternSyntaxException;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.contentassist.ComboContentAssistSubjectAdapter;
import org.eclipse.jface.contentassist.SubjectControlContentAssistant;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.text.DefaultInformationControl;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IInformationControl;
import org.eclipse.jface.text.IInformationControlCreator;
import org.eclipse.jface.text.ITextSelection;
import org.eclipse.jface.text.TextSelection;
import org.eclipse.jface.text.contentassist.IContentAssistant;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.ST;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.events.ModifyEvent;
import org.eclipse.swt.events.ModifyListener;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Combo;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.contentassist.ContentAssistHandler;
import org.eclipse.ui.forms.events.ExpansionAdapter;
import org.eclipse.ui.forms.events.ExpansionEvent;
import org.eclipse.ui.forms.widgets.Form;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.forms.widgets.Section;
import org.eclipse.ui.part.ViewPart;
import org.eclipse.ui.texteditor.ITextEditor;
import org.outlook.eclipse.plugins.regexp4eclipse.Messages;
import org.outlook.eclipse.plugins.regexp4eclipse.Regexp4EclipseActivator;
import org.outlook.eclipse.plugins.regexp4eclipse.StringUtils;
import org.outlook.eclipse.plugins.regexp4eclipse.actions.GrepAction;
import org.outlook.eclipse.plugins.regexp4eclipse.actions.JCopyAction;
import org.outlook.eclipse.plugins.regexp4eclipse.actions.KeepREAction;
import org.outlook.eclipse.plugins.regexp4eclipse.actions.LoadTestTextAction;
import org.outlook.eclipse.plugins.regexp4eclipse.actions.OrganizeREsAction;
import org.outlook.eclipse.plugins.regexp4eclipse.actions.OrganizeTestTextsAction;
import org.outlook.eclipse.plugins.regexp4eclipse.actions.SaveTestTextAction;
import org.outlook.eclipse.plugins.regexp4eclipse.actions.UndoManager;
import org.outlook.eclipse.plugins.regexp4eclipse.actions.UseJDKREAction;
import org.outlook.eclipse.plugins.regexp4eclipse.actions.UseJRegexAction;
import org.outlook.eclipse.plugins.regexp4eclipse.actions.UseJakartaRegexpAction;
import org.outlook.eclipse.plugins.regexp4eclipse.actions.UseOROAwkREAction;
import org.outlook.eclipse.plugins.regexp4eclipse.actions.UseOROPerlREAction;
import org.outlook.eclipse.plugins.regexp4eclipse.component.StyledText;
import org.outlook.eclipse.plugins.regexp4eclipse.component.StyledText.ActionCode;
import org.outlook.eclipse.plugins.regexp4eclipse.dialogs.OrganizeREsDialog;
import org.outlook.eclipse.plugins.regexp4eclipse.dialogs.OrganizeTestTextDialog;
import org.outlook.eclipse.plugins.regexp4eclipse.dialogs.REEditDialog;
import org.outlook.eclipse.plugins.regexp4eclipse.dialogs.SimpleTextDialog;
import org.outlook.eclipse.plugins.regexp4eclipse.objects.RegularExpression;
import org.outlook.eclipse.plugins.regexp4eclipse.preferences.QuickRExPreferencesPage;
import org.outlook.eclipse.plugins.regexp4eclipse.regexp.Flag;
import org.outlook.eclipse.plugins.regexp4eclipse.regexp.Match;
import org.outlook.eclipse.plugins.regexp4eclipse.regexp.MatchSetFactory;
import org.outlook.eclipse.plugins.regexp4eclipse.regexp.RegExpContentAssistProcessor;
import org.outlook.eclipse.plugins.regexp4eclipse.regexp.RegularExpressionHits;

/**
 * This sample class demonstrates how to plug-in a new workbench view. The view
 * shows data obtained from the model. The sample creates a dummy model on the
 * fly, but a real implementation would connect to the model available either in
 * this or another plug-in (e.g. the workspace). The view is connected to the
 * model using a content provider.
 * <p>
 * The view uses a label provider to define how model objects should be
 * presented in the view. Each view can present the same model objects using
 * different labels and icons, if needed. Alternatively, a single label provider
 * can be shared between views in order to ensure that objects of the same type
 * are presented in the same way everywhere.
 * <p>
 */

/**
 * @author watson.wu@hotmail.com
 */
public class Regexp4EclipseView extends ViewPart {

	/**
	 * The ID of the view as specified by the extension.
	 */
	public static final String ID = "org.outlook.eclipse.plugins.regexp4eclipse.views.Regexp4EclipseView";

	private Combo regExpCombo;

	private StyledText testText;

	private Label globalMatch;

	private Label matches;

	private Label groups;

	private Button liveEvalButton;

	private Button evaluateButton;

	private Button previousButton;

	private Button nextButton;

	private Button previousGroupButton;

	private Button nextGroupButton;

	private RegularExpressionHits hits = new RegularExpressionHits();

	private Action organizeREsAction;

	private Action organizeTestTextsAction;

	private static final String MATCH_BG_COLOR_KEY = "org.outlook.eclipse.plugins.regexp4eclipse.matchBgColor";

	private static final String MATCH_FG_COLOR_KEY = "org.outlook.eclipse.plugins.regexp4eclipse.matchFgColor";

	private static final String CURRENT_MATCH_BG_COLOR_KEY = "org.outlook.eclipse.plugins.regexp4eclipse.currentMatchBgColor";

	private static final String CURRENT_MATCH_FG_COLOR_KEY = "org.outlook.eclipse.plugins.regexp4eclipse.currentMatchFgColor";

	private static final String NOT_EVALUATED_BG_COLOR_KEY = "org.outlook.eclipse.plugins.regexp4eclipse.notEvaluatedBgColor";

	public static final String EDITOR_FONT_KEY = "org.outlook.eclipse.plugins.regexp4eclipse.textfontDefinition";

	private SubjectControlContentAssistant regExpContentAssistant;

	private Action useJDKREAction;

	private Action useOROPerlREAction;

	private Action useOROAWKAction;

	private Action useJRegexAction;

	private Action useJakartaRegexpAction;

	private Collection currentFlags = new Vector();

	private String msg = "";

	private Action keepREAction;

	private Action saveTextAction;

	private Action loadTextAction;

	private Action jcopyAction;

	private Action grepAction;

	private boolean liveEval;

	private Button editButton;

	private Point lastRESelection = new Point(0, 0);

	protected boolean startEvaluate = true;

	private Button extendCheck;

	protected int replaceIndex;

	/**
	 * The constructor.
	 */
	public Regexp4EclipseView() {
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.ui.IWorkbenchPart#createPartControl(org.eclipse.swt.widgets
	 * .Composite)
	 */
	public void createPartControl(Composite parent) {
		createViewContents(parent);
		makeActions();
		contributeToActionBars();
		initializeCurrentFlags();
		liveEval = Regexp4EclipseActivator.getDefault().isLiveEvaluation();
		liveEvalButton.setSelection(liveEval);
		evaluateButton.setEnabled(!liveEval);
	}

	private void initializeCurrentFlags() {
		for (Iterator iter = MatchSetFactory.getAllSupportedFlags().iterator(); iter
				.hasNext();) {
			Flag element = (Flag) iter.next();
			if (Regexp4EclipseActivator.getDefault().isFlagSaved(element)) {
				currentFlags.add(element);
			}
		}
	}

	private void createViewContents(Composite parent) {
		FormToolkit tk = new FormToolkit(parent.getDisplay());
		Form form = tk.createForm(parent);
		GridLayout layout = new GridLayout();

		layout.numColumns = 5;

		form.getBody().setLayout(layout);

		createFirstRow(tk, form);

		createExtendRow(tk, form);
		
		createSecondRow(tk, form);

		createNavigationSection(tk, form);

		createFlagsSection(tk, form);
	}

	private void createNavigationSection(FormToolkit tk, final Form form) {
		GridData gd;
		final Section section = tk.createSection(form.getBody(),
				Section.TWISTIE);
		gd = new GridData(GridData.FILL_HORIZONTAL);
		gd.grabExcessHorizontalSpace = true;
		gd.horizontalSpan = 5;
		section.setLayoutData(gd);
		section.setText(Messages
				.getString("views.QuickRExView.global.navigation"));
		tk.createCompositeSeparator(section);
		section.addExpansionListener(new ExpansionAdapter() {
			public void expansionStateChanged(ExpansionEvent e) {
				Regexp4EclipseActivator
						.getDefault()
						.getPreferenceStore()
						.setValue(
								Regexp4EclipseActivator.EXPAND_NAVIGATION_SECTION,
								section.isExpanded());
				form.redraw();
			}
		});
		if (Regexp4EclipseActivator.getDefault().getPreferenceStore().contains(
				Regexp4EclipseActivator.EXPAND_NAVIGATION_SECTION)) {
			section.setExpanded(Regexp4EclipseActivator.getDefault()
					.getPreferenceStore().getBoolean(
							Regexp4EclipseActivator.EXPAND_NAVIGATION_SECTION));
		} else {
			Regexp4EclipseActivator.getDefault().getPreferenceStore().setValue(
					Regexp4EclipseActivator.EXPAND_NAVIGATION_SECTION, true);
			Regexp4EclipseActivator.getDefault().getPreferenceStore()
					.setDefault(
							Regexp4EclipseActivator.EXPAND_NAVIGATION_SECTION,
							true);
			section.setExpanded(true);
		}
		Composite client = tk.createComposite(section);
		GridLayout layout = new GridLayout();
		layout.numColumns = 4;
		client.setLayout(layout);
		gd = new GridData();
		gd.horizontalSpan = 2;
		gd.grabExcessHorizontalSpace = true;
		client.setLayoutData(gd);

		createThirdRow(tk, client);

		createFourthRow(tk, client);

		createFifthRow(tk, client);

		section.setClient(client);

	}

	private void createFlagsSection(FormToolkit tk, final Form form) {
		GridData gd;
		Section section = tk.createSection(form.getBody(), Section.DESCRIPTION
				| Section.TWISTIE);
		gd = new GridData(GridData.FILL_HORIZONTAL);
		gd.grabExcessHorizontalSpace = true;
		gd.horizontalSpan = 5;
		section.setLayoutData(gd);
		section.setText(Messages.getString("views.QuickRExView.global.flags"));
		tk.createCompositeSeparator(section);
		section
				.setDescription(Messages
						.getString("views.QuickRExView.global.flags.description") + msg);
		section.addExpansionListener(new ExpansionAdapter() {
			public void expansionStateChanged(ExpansionEvent e) {
				form.redraw();
			}
		});
		Composite client = tk.createComposite(section);
		GridLayout layout = new GridLayout();
		layout.numColumns = MatchSetFactory.getMaxFlagColumns() + 1;
		client.setLayout(layout);
		gd = new GridData();
		gd.horizontalSpan = 2;
		gd.grabExcessHorizontalSpace = true;
		client.setLayoutData(gd);

		createFlagFlavourSection(
				tk,
				client,
				layout,
				gd,
				Messages.getString("views.QuickRExView.jdk.flags"), MatchSetFactory.JAVA_FLAVOUR);
		createFlagFlavourSection(
				tk,
				client,
				layout,
				gd,
				Messages.getString("views.QuickRExView.perl.flags"), MatchSetFactory.ORO_PERL_FLAVOUR);
		createFlagFlavourSection(
				tk,
				client,
				layout,
				gd,
				Messages.getString("views.QuickRExView.awk.flags"), MatchSetFactory.ORO_AWK_FLAVOUR);
		createFlagFlavourSection(
				tk,
				client,
				layout,
				gd,
				Messages.getString("views.QuickRExView.jregex.flags"), MatchSetFactory.JREGEX_FLAVOUR);
		createFlagFlavourSection(
				tk,
				client,
				layout,
				gd,
				Messages.getString("views.QuickRExView.jakartaRegexp.flags"), MatchSetFactory.JAKARTA_REGEXP_FLAVOUR);

		section.setClient(client);
	}

	/*
	 * Creates a line of flags. This is a helper for the Method
	 * createFlagSection. @param tk The FormToolkit to use @param client The
	 * Composite Client
	 * 
	 * @param layout The GridLayout to use. @param gd The GridData to fill.
	 * @param text The text for the labe at the beginning. @param flavour The
	 * Flavour to use from MatchSetFactory
	 * 
	 * @see org.outlook.eclipse.plugins.regexp4eclipse.regexp.MatchSetFactory
	 */
	private void createFlagFlavourSection(FormToolkit tk, Composite client,
			GridLayout layout, GridData gd, String text, int flavour) {
		Label l = tk.createLabel(client, text);
		int nButtons = 1;
		Collection jdkFlags = MatchSetFactory.getAllFlags(flavour);
		for (Iterator iter = jdkFlags.iterator(); iter.hasNext();) {
			nButtons++;
			final Flag element = (Flag) iter.next();
			final Button checkButton = tk.createButton(client, element
					.getName(), SWT.CHECK);
			gd = new GridData(GridData.VERTICAL_ALIGN_BEGINNING
					| GridData.HORIZONTAL_ALIGN_FILL);
			gd.grabExcessHorizontalSpace = false;
			checkButton.setLayoutData(gd);
			checkButton.setToolTipText(element.getDescription());
			checkButton.setSelection(Regexp4EclipseActivator.getDefault()
					.isFlagSaved(element));
			checkButton.addSelectionListener(new SelectionListener() {
				public void widgetSelected(SelectionEvent p_e) {
					if (checkButton.getSelection()) {
						currentFlags.add(element);
					} else {
						currentFlags.remove(element);
					}
					updateEvaluation();
				}

				public void widgetDefaultSelected(SelectionEvent p_e) {
				}
			});
		}
		while (nButtons < layout.numColumns) {
			nButtons++;
			Label fillLabel = tk.createLabel(client, "");
		}
	}

	private void createFifthRow(FormToolkit tk, Composite client) {
		GridData gd;
		// Fourth row...
		Label groupsLabel = tk.createLabel(client, Messages
				.getString("views.QuickRExView.fifthrow.label"));
		gd = new GridData();
		gd.grabExcessHorizontalSpace = false;
		groupsLabel.setLayoutData(gd);
		previousGroupButton = tk.createButton(client, Messages
				.getString("views.QuickRExView.fifthrow.prev"), SWT.PUSH);
		gd = new GridData();
		gd.grabExcessHorizontalSpace = false;
		previousGroupButton.setLayoutData(gd);
		previousGroupButton.addSelectionListener(new SelectionListener() {
			public void widgetSelected(SelectionEvent p_e) {
				handlePreviousGroupButtonPressed();
			}

			public void widgetDefaultSelected(SelectionEvent p_e) {
			}
		});
		previousGroupButton.setEnabled(false);
		nextGroupButton = tk.createButton(client, Messages
				.getString("views.QuickRExView.fifthrow.next"), SWT.PUSH);
		gd = new GridData(GridData.VERTICAL_ALIGN_END);
		gd.grabExcessHorizontalSpace = false;
		nextGroupButton.setLayoutData(gd);
		nextGroupButton.addSelectionListener(new SelectionListener() {
			public void widgetSelected(SelectionEvent p_e) {
				handleNextGroupButtonPressed();
			}

			public void widgetDefaultSelected(SelectionEvent p_e) {
			}
		});
		nextGroupButton.setEnabled(false);
		groups = tk.createLabel(client, "");
		gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL
				| GridData.GRAB_HORIZONTAL);
		gd.grabExcessHorizontalSpace = true;
		groups.setLayoutData(gd);
	}

	private void createFourthRow(FormToolkit tk, Composite client) {
		GridData gd;
		// Third row...
		Label regExpResult = tk.createLabel(client, Messages
				.getString("views.QuickRExView.fourthrow.label"));
		gd = new GridData();
		gd.grabExcessHorizontalSpace = false;
		regExpResult.setLayoutData(gd);
		previousButton = tk.createButton(client, Messages
				.getString("views.QuickRExView.fourthrow.prev"), SWT.PUSH);
		gd = new GridData();
		gd.grabExcessHorizontalSpace = false;
		previousButton.setLayoutData(gd);
		previousButton.addSelectionListener(new SelectionListener() {
			public void widgetSelected(SelectionEvent p_e) {
				handlePreviousButtonPressed();
			}

			public void widgetDefaultSelected(SelectionEvent p_e) {
			}
		});
		previousButton.setEnabled(false);
		nextButton = tk.createButton(client, Messages
				.getString("views.QuickRExView.fourthrow.next"), SWT.PUSH);
		gd = new GridData(GridData.VERTICAL_ALIGN_END);
		gd.grabExcessHorizontalSpace = false;
		nextButton.setLayoutData(gd);
		nextButton.addSelectionListener(new SelectionListener() {
			public void widgetSelected(SelectionEvent p_e) {
				handleNextButtonPressed();
			}

			public void widgetDefaultSelected(SelectionEvent p_e) {
			}
		});
		nextButton.setEnabled(false);
		matches = tk.createLabel(client, Messages
				.getString("views.QuickRExView.fourthrow.message"));
		gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL
				| GridData.GRAB_HORIZONTAL);
		gd.grabExcessHorizontalSpace = true;
		matches.setLayoutData(gd);
	}

	private void createThirdRow(FormToolkit tk, Composite client) {
		liveEvalButton = tk
				.createButton(
						client,
						Messages
								.getString("views.QuickRExView.button.toggleLiveEvaluation.label"), SWT.CHECK);
		GridData gd = new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING);
		gd.grabExcessHorizontalSpace = false;
		liveEvalButton.setLayoutData(gd);
		liveEvalButton.addSelectionListener(new SelectionListener() {
			public void widgetSelected(SelectionEvent p_e) {
				if (liveEvalButton.getSelection()) {
					Regexp4EclipseActivator
							.getDefault()
							.getPreferenceStore()
							.setValue(QuickRExPreferencesPage.P_LIVE_EVAL, true);
					liveEval = true;
					evaluateButton.setEnabled(false);
					evaluate();
				} else {
					Regexp4EclipseActivator.getDefault().getPreferenceStore()
							.setValue(QuickRExPreferencesPage.P_LIVE_EVAL,
									false);
					liveEval = false;
					evaluateButton.setEnabled(true);
				}
			}

			public void widgetDefaultSelected(SelectionEvent p_e) {
			}
		});
		liveEvalButton.setEnabled(true);
		liveEvalButton.setSelection(true);
		liveEvalButton
				.setToolTipText(Messages
						.getString("views.QuickRExView.button.toggleLiveEvaluation.tooltip"));
		evaluateButton = tk
				.createButton(
						client,
						Messages
								.getString("views.QuickRExView.button.evaluate.label"), SWT.PUSH);
		gd = new GridData(GridData.HORIZONTAL_ALIGN_END);
		gd.grabExcessHorizontalSpace = false;
		evaluateButton.setLayoutData(gd);
		evaluateButton.addSelectionListener(new SelectionListener() {
			public void widgetSelected(SelectionEvent p_e) {
				evaluate();
			}

			public void widgetDefaultSelected(SelectionEvent p_e) {
			}
		});
		evaluateButton.setEnabled(!liveEval);
		globalMatch = tk.createLabel(client, "");
		gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL
				| GridData.GRAB_HORIZONTAL);
		gd.grabExcessHorizontalSpace = true;
		gd.horizontalSpan = 2;
		globalMatch.setLayoutData(gd);
	}

	private void createSecondRow(FormToolkit tk, Form form) {
		GridData gd;
		// Second row
		Label testTextEnter = tk.createLabel(form.getBody(), Messages
				.getString("views.QuickRExView.secondrow.label"));
		gd = new GridData(GridData.VERTICAL_ALIGN_BEGINNING);
		gd.grabExcessHorizontalSpace = false;
		testTextEnter.setLayoutData(gd);
		testText = new StyledText(form.getBody(), SWT.BORDER | SWT.MULTI
				| SWT.H_SCROLL | SWT.V_SCROLL);
		testText.setFont(JFaceResources.getFont(EDITOR_FONT_KEY));
		gd = new GridData(GridData.FILL_BOTH);
		gd.grabExcessHorizontalSpace = true;
		gd.grabExcessVerticalSpace = true;

		gd.horizontalSpan = 4;
		testText.setLayoutData(gd);
		testText.addModifyListener(new ModifyListener() {
			public void modifyText(ModifyEvent p_e) {
				handleTestTextModified();
			}
		});
		
		testText.setKeyBinding('A' | SWT.CTRL, ST.SELECT_ALL);

		testText.setKeyBinding('Z' | SWT.CTRL, ActionCode.UNDO);
		testText.setKeyBinding('Y' | SWT.CTRL, ActionCode.REDO);
		testText.setKeyBinding('F' | SWT.CTRL, ActionCode.CLEAR);
		testText.setKeyBinding('D' | SWT.CTRL, ActionCode.DELETE);

		UndoManager undoManager = new UndoManager(50);
		undoManager.connect(testText);
		testText.setUndoManager(undoManager);
		
		tk.adapt(testText, true, true);
	}

	private void createFirstRow(FormToolkit tk, Form form) {
		GridData gd;
		// First row...
		Label regExpEnter = tk.createLabel(form.getBody(), Messages
				.getString("views.QuickRExView.firstrow.label"));
		gd = new GridData();
		gd.horizontalAlignment = GridData.BEGINNING;
		gd.grabExcessHorizontalSpace = false;
		regExpEnter.setLayoutData(gd);
		regExpCombo = new Combo(form.getBody(), SWT.DROP_DOWN);
		regExpCombo.setItems(Regexp4EclipseActivator.getDefault()
				.getRegularExpressions());
		regExpCombo.setFont(JFaceResources.getFont(EDITOR_FONT_KEY));
		gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL
				| GridData.GRAB_HORIZONTAL);
		gd.horizontalSpan = 3;
		gd.grabExcessHorizontalSpace = true;
		regExpCombo.setLayoutData(gd);
		regExpCombo.addModifyListener(new ModifyListener() {
			public void modifyText(ModifyEvent p_e) {
				handleRegExpModified();
			}
		});
		regExpCombo.addFocusListener(new FocusListener() {
			public void focusGained(FocusEvent p_e) {
				// This is a hack to keep the Previous- and Next-Buttons from
				// generating
				// selections in the component...
				regExpCombo.clearSelection();
			}

			public void focusLost(FocusEvent p_e) {
				// This is a hack to keep the Previous- and Next-Buttons from
				// generating
				// selections in the component...
				regExpCombo.clearSelection();
			}
		});
		regExpCombo.addKeyListener(new KeyListener() {
			public void keyPressed(KeyEvent e) {
				lastRESelection = regExpCombo.getSelection();
			}

			public void keyReleased(KeyEvent e) {
				lastRESelection = regExpCombo.getSelection();
			}
		});
		regExpCombo.addMouseListener(new MouseListener() {
			public void mouseDoubleClick(MouseEvent e) {
			}

			public void mouseDown(MouseEvent e) {
				lastRESelection = regExpCombo.getSelection();
			}

			public void mouseUp(MouseEvent e) {
			}
		});
		tk.adapt(regExpCombo, true, true);

		editButton = tk.createButton(form.getBody(), Messages
				.getString("views.QuickRExView.button.edit.label"), SWT.PUSH);
		gd = new GridData(GridData.HORIZONTAL_ALIGN_END);
		gd.grabExcessHorizontalSpace = false;
		editButton.setLayoutData(gd);
		editButton.addSelectionListener(new SelectionListener() {
			public void widgetSelected(SelectionEvent p_e) {
				edit();
			}

			public void widgetDefaultSelected(SelectionEvent p_e) {
			}
		});
		editButton.setEnabled(true);

		createRegExpContentAssist();
	}
	
	private void createExtendRow(FormToolkit tk, Form form) {
		GridData gd;
		Label replaceEnter = tk.createLabel(form.getBody(), Messages
				.getString("views.QuickRExView.replace.label"));
		gd = new GridData();
		gd.horizontalAlignment = GridData.BEGINNING;
		gd.grabExcessHorizontalSpace = false;
		replaceEnter.setLayoutData(gd);
	    
		final Combo replaceCombo = new Combo(form.getBody(), SWT.DROP_DOWN);
		replaceCombo.setItems(Regexp4EclipseActivator.getDefault()
				.getRegularExpressions());
		replaceCombo.setFont(JFaceResources.getFont(EDITOR_FONT_KEY));
		gd = new GridData(GridData.HORIZONTAL_ALIGN_FILL | GridData.GRAB_HORIZONTAL);
//		gd.horizontalSpan = 1;
		gd.grabExcessHorizontalSpace = true;
		replaceCombo.setLayoutData(gd);
		replaceCombo.addModifyListener(new ModifyListener() {
			
			@Override
			public void modifyText(ModifyEvent arg0) {
				replaceIndex = 1;
			}
		});

		gd = new GridData();
		gd.grabExcessHorizontalSpace = false;
		Button replaceButton = new Button(form.getBody(), SWT.PUSH);
//		replaceButton.setLayoutData(gd);
		replaceButton.setText(Messages.getString("views.QuickRExView.replace.button.label"));
		replaceButton.addSelectionListener(new SelectionListener() {
			public void widgetSelected(SelectionEvent p_e) {
				//TODO
				if(replaceCombo.getText() == null || regExpCombo.getText()== null) {
					matches.setText(Messages.getString("views.QuickRExView.replace.message"));
				}
				
				try {
					replaceContent(replaceCombo.getText(), false);
				} catch (Exception e) {
				}
			}

			public void widgetDefaultSelected(SelectionEvent p_e) {
			}
		});
		Button replaceAllButton = new Button(form.getBody(), SWT.PUSH);
//		replaceAllButton.setLayoutData(gd);
		replaceAllButton.setText(Messages.getString("views.QuickRExView.replaceAll.button.label"));
		replaceAllButton.addSelectionListener(new SelectionListener() {
			public void widgetSelected(SelectionEvent p_e) {
				//TODO
				if(replaceCombo.getText() == null || regExpCombo.getText()== null) {
					matches.setText(Messages.getString("views.QuickRExView.replace.message"));
				}

				try {
					replaceContent(replaceCombo.getText(), true);
				} catch (Exception e) {
				}
			}

			public void widgetDefaultSelected(SelectionEvent p_e) {
			}
		});
		
		extendCheck = tk.createButton(form.getBody(), Messages.getString("views.QuickRExView.extend.lebel"), SWT.CHECK);
//		extendCheck.setLayoutData(gd);
		extendCheck.setToolTipText(Messages.getString("views.QuickRExView.extend.description"));
//		extendCheck.addSelectionListener(new SelectionListener() {
//
//			@Override
//			public void widgetSelected(SelectionEvent arg0) {
//				
//			}
//			
//			@Override
//			public void widgetDefaultSelected(SelectionEvent arg0) {
//				
//			}
//		});
	}

	private void replaceContent(String text, boolean isAll) throws Exception {
		//validate(text);
		startEvaluate = false;
		try {
			org.outlook.xnotepad.command.action.Comman comman = null;
			if(extendCheck.getSelection()) {
				comman = new org.outlook.xnotepad.command.action.Comman(text);
			}
			String replaceText;
			if(isAll) {
				final Match[] allMatches = hits.getAllMatches();
				if (allMatches != null && allMatches.length > 0) {
					int offset = 0;
					for(Match match : allMatches) {
						try {
							replaceText = getDynamicValue(match.getText(), comman);
							testText.replaceTextRange(match.getStart()+offset, match.getText().length(), replaceText);
							offset += replaceText.length() - match.getText().length();
						} catch (Exception e) {
							e.printStackTrace();
						}
					}
				}
			} else {
				Match match = hits.getCurrentMatch();
				if(null != match) {
					replaceText = getDynamicValue(match.getText(), comman);
					testText.replaceTextRange(match.getStart(), match.getText().length(), replaceText);
				}
			}
		} finally {
			startEvaluate = true;
			evaluate();
		}
	}

	private String getDynamicValue(String text,
			org.outlook.xnotepad.command.action.Comman comman) {
		String replaceText = extendCheck.getSelection()?comman.getResult(replaceIndex++, text):text;
		return replaceText;
	}

	private void createRegExpContentAssist() {
		regExpContentAssistant = new SubjectControlContentAssistant();
		regExpContentAssistant.enableAutoActivation(false);
		regExpContentAssistant.enableAutoInsert(true);
		regExpContentAssistant.setContentAssistProcessor(
				new RegExpContentAssistProcessor(),
				IDocument.DEFAULT_CONTENT_TYPE);
		regExpContentAssistant
				.setContextInformationPopupOrientation(IContentAssistant.CONTEXT_INFO_ABOVE);
		regExpContentAssistant
				.setRestoreCompletionProposalSize(Regexp4EclipseActivator
						.getDefault().getDialogSettings());
		regExpContentAssistant
				.setInformationControlCreator(new IInformationControlCreator() {
					/*
					 * @seeorg.eclipse.jface.text.IInformationControlCreator#
					 * createInformationControl(org.eclipse.swt.widgets.Shell)
					 */
					public IInformationControl createInformationControl(
							Shell parent) {
						return new DefaultInformationControl(parent);
					}
				});
		regExpContentAssistant.install(new ComboContentAssistSubjectAdapter(
				regExpCombo));
		ContentAssistHandler.createHandlerForCombo(regExpCombo,
				regExpContentAssistant);
	}

	private void makeActions() {
		organizeREsAction = new OrganizeREsAction();

		organizeTestTextsAction = new OrganizeTestTextsAction();

		useJDKREAction = new UseJDKREAction();

		useOROPerlREAction = new UseOROPerlREAction();

		useOROAWKAction = new UseOROAwkREAction();

		useJRegexAction = new UseJRegexAction();

		useJakartaRegexpAction = new UseJakartaRegexpAction();

		keepREAction = new KeepREAction();

		saveTextAction = new SaveTestTextAction();

		loadTextAction = new LoadTestTextAction();

		jcopyAction = new JCopyAction();

		grepAction = new GrepAction();
	}

	private void contributeToActionBars() {
		IActionBars bars = getViewSite().getActionBars();
		fillLocalPullDown(bars.getMenuManager());
		IToolBarManager toolbar = getViewSite().getActionBars()
				.getToolBarManager();
		fillToolBar(toolbar);
	}

	private void fillToolBar(IToolBarManager manager) {
		manager.add(useJDKREAction);
		manager.add(useOROPerlREAction);
		manager.add(useOROAWKAction);
		manager.add(useJRegexAction);
		manager.add(useJakartaRegexpAction);
		manager.add(new Separator("UseRESeparator"));
		manager.add(jcopyAction);
		manager.add(grepAction);
		manager.add(new Separator("StoreHandleSeparator1"));
		manager.add(keepREAction);
		manager.add(saveTextAction);
		manager.add(loadTextAction);
	}

	private void fillLocalPullDown(IMenuManager manager) {
		manager.add(useJDKREAction);
		manager.add(useOROPerlREAction);
		manager.add(useOROAWKAction);
		manager.add(useJRegexAction);
		manager.add(useJakartaRegexpAction);
		manager.add(new Separator("UseRESeparator"));
		manager.add(jcopyAction);
		manager.add(grepAction);
		manager.add(new Separator("StoreHandleSeparator1"));
		manager.add(keepREAction);
		manager.add(saveTextAction);
		manager.add(loadTextAction);
		manager.add(new Separator("StoreHandleSeparator2"));
		manager.add(organizeREsAction);
		manager.add(organizeTestTextsAction);
	}

	private void redrawFourthLine() {
		nextButton.redraw();
		previousButton.redraw();
		matches.redraw();
	}

	private void redrawFifthLine() {
		nextGroupButton.redraw();
		previousGroupButton.redraw();
		groups.redraw();
	}

	private ITextEditor getActiveEditor() {
		if (PlatformUI.getWorkbench().getActiveWorkbenchWindow()
				.getActivePage().getActiveEditor() instanceof ITextEditor) {
			return (ITextEditor) PlatformUI.getWorkbench()
					.getActiveWorkbenchWindow().getActivePage()
					.getActiveEditor();
		} else {
			return null;
		}
	}

	/**
	 * Sets the RE-flavour to be the JDK-one and triggers a re-evaluation
	 */
	public void setUseJavaRE() {
		Regexp4EclipseActivator.getDefault().useJavaRE();
		// This is a hack since there is no direct way of getting rid of the
		// completion-proposal popup...
		String oldRegExp = regExpCombo.getText();
		regExpCombo.setText(oldRegExp + " ");
		regExpCombo.setText(oldRegExp);
		updateEvaluation();
	}

	/**
	 * Sets the RE-flavour to be the ORO-Perl-one and triggers a re-evaluation
	 */
	public void setUseOROPerlRE() {
		Regexp4EclipseActivator.getDefault().useOROPerlRE();
		// This is a hack since there is no direct way of getting rid of the
		// completion-proposal popup...
		String oldRegExp = regExpCombo.getText();
		regExpCombo.setText(oldRegExp + " ");
		regExpCombo.setText(oldRegExp);
		updateEvaluation();
	}

	/**
	 * Sets the RE-flavour to be the ORO-Awk-one and triggers a re-evaluation
	 */
	public void setUseOROAwkRE() {
		Regexp4EclipseActivator.getDefault().useOROAwkRE();
		// This is a hack since there is no direct way of getting rid of the
		// completion-proposal popup...
		String oldRegExp = regExpCombo.getText();
		regExpCombo.setText(oldRegExp + " ");
		regExpCombo.setText(oldRegExp);
		updateEvaluation();
	}

	/**
	 * Sets the RE-flavour to be the JRegex-one and triggers a re-evaluation
	 */
	public void setUseJRegex() {
		Regexp4EclipseActivator.getDefault().useJRegex();
		// This is a hack since there is no direct way of getting rid of the
		// completion-proposal popup...
		String oldRegExp = regExpCombo.getText();
		regExpCombo.setText(oldRegExp + " ");
		regExpCombo.setText(oldRegExp);
		updateEvaluation();
	}

	/**
	 * Sets the RE-flavour to be the Jakarta-Regexp-one and triggers a
	 * re-evaluation
	 */
	public void setUseJakartaRegexp() {
		Regexp4EclipseActivator.getDefault().useJakartaRegexp();
		// This is a hack since there is no direct way of getting rid of the
		// completion-proposal popup...
		String oldRegExp = regExpCombo.getText();
		regExpCombo.setText(oldRegExp + " ");
		regExpCombo.setText(oldRegExp);
		updateEvaluation();
	}

	/**
	 * The handle-method for organizing saved RegExp.s
	 */
	public void handleOrganizeREs() {
		OrganizeREsDialog dlg = new OrganizeREsDialog(getSite().getShell());
		dlg.open();
		regExpCombo.setItems(Regexp4EclipseActivator.getDefault()
				.getRegularExpressions());
	}

	/**
	 * The handle-method for organizing saved Test-texts
	 */
	public void handleOrganizeTexts() {
		OrganizeTestTextDialog dlg = new OrganizeTestTextDialog(getSite()
				.getShell(), OrganizeTestTextDialog.TYPE_ORGANIZE);
		dlg.open();
	}

	/**
	 * The handle-method for grepping
	 */
	public void handleGrepButtonPressed() {
		SimpleTextDialog dlg = new SimpleTextDialog(getSite().getShell(),
				Messages.getString("views.QuickRExView.dlg.title"), hits.grep());
		dlg.open();
	}

	/**
	 * The handle-method for copying to the current editor (escaping for Java)
	 */
	public void handleCopyButtonPressed() {
		copyToEditor(StringUtils.escapeForJava(regExpCombo.getText()));
	}

	private void copyToEditor(String string) {
		try {
			int currentOffset = ((ITextSelection) getActiveEditor()
					.getSelectionProvider().getSelection()).getOffset();
			int currentLength = ((ITextSelection) getActiveEditor()
					.getSelectionProvider().getSelection()).getLength();
			getActiveEditor().getDocumentProvider().getDocument(
					getActiveEditor().getEditorInput()).replace(currentOffset,
					currentLength, string);
			getActiveEditor().getSelectionProvider().setSelection(
					new TextSelection(currentOffset, string.length()));
		} catch (Throwable t) {
			// nop...
		}
	}

	/**
	 * The handle-method for loading test-texts
	 */
	public void handleLoadTextButtonPressed() {
		OrganizeTestTextDialog dlg = new OrganizeTestTextDialog(getSite()
				.getShell(), OrganizeTestTextDialog.TYPE_LOAD);
		dlg.open();
		if (dlg.getSelectedText() != null) {
			testText.setText(dlg.getSelectedText().getText());
		}
	}

	/**
	 * The handle-method for saving test-texts
	 */
	public void handleSaveTextButtonPressed() {
		OrganizeTestTextDialog dlg = new OrganizeTestTextDialog(getSite()
				.getShell(), OrganizeTestTextDialog.TYPE_SAVE);
		dlg.setTextToSave(testText.getText());
		dlg.open();
		if (dlg.getSaveInformation() != null) {
			Regexp4EclipseActivator.getDefault().addTestText(
					dlg.getSaveInformation());
		}
	}

	private void handleNextGroupButtonPressed() {
		hits.getCurrentMatch().toNextGroup();
		groups
				.setText(escapeMnemonic(Messages
						.getString(
								"views.QuickRExView.result.group", new Object[] { new Integer(hits.getCurrentMatch().getNumberOfGroups()),
										fetchGroupID(),
										hits.getCurrentMatch()
												.getCurrentGroup().getText() })));
		nextGroupButton.setEnabled(hits.getCurrentMatch().hasNextGroup());
		previousGroupButton.setEnabled(hits.getCurrentMatch()
				.hasPreviousGroup());
		updateMatchView(hits.getCurrentMatch());
	}

	private void handlePreviousGroupButtonPressed() {
		hits.getCurrentMatch().toPreviousGroup();
		groups
				.setText(escapeMnemonic(Messages
						.getString(
								"views.QuickRExView.result.group", new Object[] { new Integer(hits.getCurrentMatch().getNumberOfGroups()),
										fetchGroupID(),
										hits.getCurrentMatch()
												.getCurrentGroup().getText() })));
		nextGroupButton.setEnabled(hits.getCurrentMatch().hasNextGroup());
		previousGroupButton.setEnabled(hits.getCurrentMatch()
				.hasPreviousGroup());
		updateMatchView(hits.getCurrentMatch());
	}

	private void handleNextButtonPressed() {
		hits.toNextMatch();
		Match match = hits.getCurrentMatch();
		matches
				.setText(Messages
						.getString(
								"views.QuickRExView.result.match", new Object[] { new Integer(hits.getNumberOfMatches()),
										new Integer(match.getStart()),
										new Integer(match.getEnd()) }));
		updateMatchView(match);
		nextButton.setEnabled(hits.hasNextMatch());
		previousButton.setEnabled(hits.hasPreviousMatch());
		if (hits.getCurrentMatch().getNumberOfGroups() > 0) {
			groups
					.setText(escapeMnemonic(Messages
							.getString(
									"views.QuickRExView.result.group", new Object[] { new Integer(hits.getCurrentMatch().getNumberOfGroups()),
											fetchGroupID(),
											hits.getCurrentMatch()
													.getCurrentGroup()
													.getText() })));
		} else {
			groups.setText(Messages
					.getString("views.QuickRExView.result.group.none"));
		}
		nextGroupButton.setEnabled(hits.getCurrentMatch().hasNextGroup());
		previousGroupButton.setEnabled(hits.getCurrentMatch()
				.hasPreviousGroup());
	}

	private void handlePreviousButtonPressed() {
		hits.toPreviousMatch();
		Match match = hits.getCurrentMatch();
		matches
				.setText(Messages
						.getString(
								"views.QuickRExView.result.match", new Object[] { new Integer(hits.getNumberOfMatches()),
										new Integer(match.getStart()),
										new Integer(match.getEnd()) }));
		updateMatchView(match);
		nextButton.setEnabled(hits.hasNextMatch());
		previousButton.setEnabled(hits.hasPreviousMatch());
		if (hits.getCurrentMatch().getNumberOfGroups() > 0) {
			groups
					.setText(escapeMnemonic(Messages
							.getString(
									"views.QuickRExView.result.group", new Object[] { new Integer(hits.getCurrentMatch().getNumberOfGroups()),
											fetchGroupID(),
											hits.getCurrentMatch()
													.getCurrentGroup()
													.getText() })));
		} else {
			groups.setText(Messages
					.getString("views.QuickRExView.result.group.none"));
		}
		nextGroupButton.setEnabled(hits.getCurrentMatch().hasNextGroup());
		previousGroupButton.setEnabled(hits.getCurrentMatch()
				.hasPreviousGroup());
	}

	private void handleTestTextModified() {
		updateEvaluation();
	}

	private void handleRegExpModified() {
		updateEvaluation();
	}

	private void updateMatchView(Match match) {
		updateMatchView(match, true);
	}

	private void updateMatchView(Match match, boolean evaluated) {
		testText.setStyleRange(new StyleRange(0, testText.getText().length(),
				null, null));
		if (!evaluated) {
			testText.setBackground(JFaceResources.getColorRegistry().get(
					NOT_EVALUATED_BG_COLOR_KEY));
		} else {
			testText.setBackground(null);
		}
		if (hits.getAllMatches() != null && hits.getAllMatches().length > 0) {
			testText.setStyleRanges(getStyleRanges(hits.getAllMatches()));
		}
		if (match != null) {
			testText.setStyleRange(new StyleRange(match.getStart(), match
					.getEnd()
					- match.getStart(), JFaceResources.getColorRegistry().get(
					CURRENT_MATCH_FG_COLOR_KEY), JFaceResources
					.getColorRegistry().get(CURRENT_MATCH_BG_COLOR_KEY),
					SWT.NORMAL));
			if (match.getCurrentGroup() != null
					&& match.getCurrentGroup().getStart() >= 0) {
				testText.setStyleRange(new StyleRange(match.getCurrentGroup()
						.getStart(), match.getCurrentGroup().getEnd()
						- match.getCurrentGroup().getStart(), JFaceResources
						.getColorRegistry().get(CURRENT_MATCH_FG_COLOR_KEY),
						JFaceResources.getColorRegistry().get(
								CURRENT_MATCH_BG_COLOR_KEY), SWT.BOLD));
			}
			// scroll horizontally if needed
			testText.setTopIndex(testText.getLineAtOffset(match.getStart()));
		}
	}

	private StyleRange[] getStyleRanges(Match[] p_matches) {
		StyleRange[] ranges = new StyleRange[p_matches.length];
		for (int i = 0; i < p_matches.length; i++) {
			ranges[i] = new StyleRange(p_matches[i].getStart(), p_matches[i]
					.getEnd()
					- p_matches[i].getStart(), JFaceResources
					.getColorRegistry().get(MATCH_FG_COLOR_KEY), JFaceResources
					.getColorRegistry().get(MATCH_BG_COLOR_KEY));
		}
		return ranges;
	}

	private void updateEvaluation() {
		if (liveEval) {
			Point selection = regExpCombo.getSelection();
			evaluate();
			regExpCombo.setSelection(selection);
		} else {
			Point selection = regExpCombo.getSelection();
			hits.reset();
			matches.setText(Messages
					.getString("views.QuickRExView.matches.notEvaluated.text"));
			groups.setText("");
			globalMatch.setText("");
			updateMatchView(null, false);
			nextButton.setEnabled(false);
			previousButton.setEnabled(false);
			nextGroupButton.setEnabled(false);
			previousGroupButton.setEnabled(false);
			regExpCombo.setSelection(selection);
		}
	}

	private void edit() {
		REEditDialog dlg = new REEditDialog(this, getSite().getShell(),
				Regexp4EclipseActivator.getDefault().getREFlavour());
		dlg.open();
		if (dlg.getSelectedText() != null) {
			regExpCombo.setText(dlg.getSelectedText());
			evaluate();
		}
	}

	private void evaluate() {
		if(!startEvaluate) return ;
		if (regExpCombo.getText() != null && testText.getText() != null) {
			matches.setForeground(null);
			matches.setText("");
			groups.setText("");

			final Boolean[] canceledEvaluation = new Boolean[1];
			try {
				final String sRegExpCombo = regExpCombo.getText();
				final String sTestText = testText.getText();
				getSite().getWorkbenchWindow().getWorkbench()
						.getProgressService().run(true, true,
								new IRunnableWithProgress() {
									public void run(IProgressMonitor monitor)
											throws InvocationTargetException,
											InterruptedException {

										// set progress-thread to low priority -
										// so the workbench has a higher
										// priority
										Thread.currentThread().setPriority(
												Thread.MIN_PRIORITY + 1);

										final boolean dontStop = !Regexp4EclipseActivator
												.getDefault()
												.getPreferenceStore()
												.getBoolean(
														QuickRExPreferencesPage.P_DO_TIMEOUT);
										long stopAfterSeconds = Regexp4EclipseActivator
												.getDefault()
												.getPreferenceStore()
												.getLong(
														QuickRExPreferencesPage.P_TIMEOUT);
										final long maxTime = System
												.currentTimeMillis()
												+ 1000 * stopAfterSeconds;

										// create a processing thread with low
										// priority
										Thread regExpThread = new Thread(
												"QuickREx-Processing") {
											public void run() {
												try {
													hits.init(sRegExpCombo,
															sTestText,
															currentFlags);
												} catch (Throwable throwable) {
													hits
															.setException(throwable);
												}
											}
										};
										regExpThread
												.setPriority(Thread.MIN_PRIORITY);
										regExpThread.start();

										// control the regExpThread and kill him
										// if time exceeded or user canceled
										// process
										boolean monitorHasTask = false;
										while (regExpThread.isAlive()
												&& (dontStop || System
														.currentTimeMillis() < maxTime)
												&& monitor.isCanceled() == false) {

											// do nothing
											Thread.yield();

											// update progressBar
											if (monitorHasTask == false) {
												monitor
														.beginTask(
																Messages
																		.getString("views.QuickRExView.tasks.processing.name"), IProgressMonitor.UNKNOWN);
												monitorHasTask = true;
											}
										}

										if (regExpThread.isAlive()) {
											// force thread to stop
											regExpThread.stop();
											canceledEvaluation[0] = Boolean.TRUE;
										}

										monitor.done();
									}
								});
			} catch (InvocationTargetException ex) {
				ex.printStackTrace();

			} catch (InterruptedException ex) {
				canceledEvaluation[0] = Boolean.TRUE;
			}

			if (Boolean.TRUE.equals(canceledEvaluation[0])) {
				// reset hits because the thread was killed and hits has an
				// unexpected state
				hits.reset();
				// user canceled progressDialog
				matches
						.setText(Messages
								.getString("views.QuickRExView.matches.cancelledEvaluation.text"));
				groups.setText("");
				globalMatch.setText("");
				updateMatchView(null, false);
				nextButton.setEnabled(false);
				previousButton.setEnabled(false);
				nextGroupButton.setEnabled(false);
				previousGroupButton.setEnabled(false);
				return;
			}

			if (hits.containsException()) {
				Throwable t = hits.getException();
				if (t instanceof PatternSyntaxException) {
					matches
							.setText(Messages
									.getString(
											"views.QuickRExView.result.match.illegalPattern", new Object[] { StringUtils.firstLine(t.getMessage()) }));
				} else {
					String msg = t.getMessage();
					if (msg == null)
						msg = t.toString();
					matches
							.setText(Messages
									.getString(
											"views.QuickRExView.result.match.parserException", new Object[] { msg }));          
				}

				matches.setForeground(Display.getCurrent().getSystemColor(
						SWT.COLOR_DARK_RED));
				hits.reset();
				updateMatchView(null);
				regExpCombo.setFocus();
				groups.setText("");
				globalMatch.setText("");
				nextButton.setEnabled(false);
				previousButton.setEnabled(false);
				nextGroupButton.setEnabled(false);
				previousGroupButton.setEnabled(false);
			} else if (hits.containsMatches()) {
				Match match = hits.getCurrentMatch();
				updateMatchView(match);
				matches
						.setText(Messages
								.getString(
										"views.QuickRExView.result.match", new Object[] { new Integer(hits.getNumberOfMatches()),
												new Integer(match.getStart()),
												new Integer(match.getEnd()) }));
				globalMatch
						.setText(Messages
								.getString(
										"views.QuickRExView.result.globalMatch", new Object[] { new Boolean(hits.isGlobalMatch()) }));
				nextButton.setEnabled(hits.hasNextMatch());
				previousButton.setEnabled(hits.hasPreviousMatch());
				if (hits.getCurrentMatch().getNumberOfGroups() > 0) {
					groups
							.setText(escapeMnemonic(Messages
									.getString(
											"views.QuickRExView.result.group", new Object[] { new Integer(hits.getCurrentMatch().getNumberOfGroups()),
													fetchGroupID(),
													hits.getCurrentMatch()
															.getCurrentGroup()
															.getText() })));
				} else {
					groups.setText(Messages
							.getString("views.QuickRExView.result.group.none"));
				}
				nextGroupButton.setEnabled(hits.getCurrentMatch()
						.hasNextGroup());
				previousGroupButton.setEnabled(hits.getCurrentMatch()
						.hasPreviousGroup());
			} else {
				updateMatchView(null);
				matches.setText(Messages
						.getString("views.QuickRExView.result.match.none"));
				groups.setText("");
				globalMatch
						.setText(Messages
								.getString(
										"views.QuickRExView.result.globalMatch", new Object[] { new Boolean(hits.isGlobalMatch()) }));
				nextButton.setEnabled(false);
				previousButton.setEnabled(false);
				nextGroupButton.setEnabled(false);
				previousGroupButton.setEnabled(false);
			}
			redrawFourthLine();
			redrawFifthLine();
		}
	}

	private String escapeMnemonic(String string) {
		return string.replaceAll("&", "&&");
	}

	private String fetchGroupID() {
		int index = hits.getCurrentMatch().getCurrentGroup().getIndex();
		String ret = "" + index;

		String groupID = hits.getCurrentMatch().getCurrentGroup().getID();
		if (groupID != null)
			ret += " - {" + groupID + "}"; //$NON-NLS-2$

		return ret;
	}

	/**
	 * The handle-method for keeping the current expression
	 */
	public void handleKeepButtonPressed() {
		regExpCombo.add(regExpCombo.getText(), 0);
		Regexp4EclipseActivator.getDefault().addRegularExpression(
				new RegularExpression(regExpCombo.getText()));
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.ui.part.WorkbenchPart#setFocus()
	 */
	public void setFocus() {
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.ui.IWorkbenchPart#dispose()
	 */
	public void dispose() {
		Regexp4EclipseActivator.getDefault().saveSelectedFlagValues(
				currentFlags);
		super.dispose();
	}

	/**
	 * Set the current RE to the passed String
	 * 
	 * @param re
	 *            the String to use
	 */
	public void setRegularExpression(String re) {
		regExpCombo.setText(re);
	}

	/**
	 * Set the current test-text to the passed String
	 * 
	 * @param text
	 *            the String to use
	 */
	public void setTestText(String text) {
		testText.setText(text);
	}

	/**
	 * Returns the current RE
	 * 
	 * @return the current RE
	 */
	public String getRegularExpression() {
		return regExpCombo.getText();
	}

	/**
	 * Returns the last selection in the RE-Combo
	 * 
	 * @return the last selection
	 */
	public Point getLastComboSelection() {
		return lastRESelection;
	}
}